package com.zrkizzy.module.system.filter.login;

import com.zrkizzy.common.models.domain.system.core.User;
import com.zrkizzy.common.models.dto.system.common.LoginDTO;
import com.zrkizzy.common.security.context.UserContext;
import com.zrkizzy.module.system.exception.LoginErrorCode;
import com.zrkizzy.module.system.filter.LoginFilter;
import com.zrkizzy.module.system.mapper.core.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.Objects;


/**
 * 用户名密码校验责任链节点
 *
 * @author zhangrongkang
 * @since 2023/8/31
 */
@Slf4j
@Component("usernamePasswordValidationFilter")
public class UsernamePasswordValidationFilter extends LoginFilter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;

    /**
     * 当前节点登录处理逻辑
     *
     * @param loginDTO 用户登录数据传输对象
     */
    @Override
    public void handleLogin(LoginDTO loginDTO) {
        log.info("-------------------- 进入用户名密码校验责任链节点 --------------------");
        // 获取用户名和密码
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        // 数据库中查询对应的User对象
        User user = userMapper.getUserByUsername(username);
        // 校验用户是否存在
        validateUserExist(user);
        // 如果账户被冻结
        validateUserFrozen(user);
        // 校验密码
        validateUserPassword(password, user.getPassword());
        // 存储当前用户属性到线程变量
        UserContext.setUser(user);
        log.info("-------------------- 离开用户名密码校验责任链节点 --------------------");
        // 进行其余校验
        loginFilter.handleLogin(loginDTO);
    }

    /**
     * 校验用户密码
     *
     * @param password 用户输入密码
     * @param userPassword 用户密码
     */
    private void validateUserPassword(String password, String userPassword) {
        if (!passwordEncoder.matches(password, userPassword)) {
            // 抛出密码错误异常
            throw LoginErrorCode.USER_PASSWORD_ERROR.exception();
        }
    }

    /**
     * 校验用户账户是否被冻结
     *
     * @param user 查询出的用户对象
     */
    private void validateUserFrozen(User user) {
        if (!user.getStatus()) {
            throw LoginErrorCode.USER_ACCOUNT_FROZEN.exception();
        }
    }

    /**
     * 校验当前用户是否存在
     *
     * @param user 查询出的用户对象
     */
    private void validateUserExist(User user) {
        if (Objects.isNull(user)) {
            // 用户不存在
            log.error("用户不存在");
            throw LoginErrorCode.USER_ACCOUNT_NOT_EXIST.exception();
        }
    }
}
